﻿// Author: Vana Genica Cosmin

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Web;

namespace FileUpload
{
    public static class CFileUpload
    {
        private static IDictionary<Guid, int>requests = new Dictionary<Guid, int>();
   
        public static void RegisterHandler(HttpRequest request, string path)
        {
            Guid id = Guid.Parse(request.Url.Query.Substring(request.Url.Query.IndexOf("=") + 1));
            string filename = id.ToString() + "1";
            string directory = path + @"\" + id.ToString();
            Directory.CreateDirectory(directory);
            string fileFullPath = directory + @"\" + filename;
            string fileHeader = null;
            string realFileName;
   
            if (requests.ContainsKey(id))
                throw new Exception();
           requests.Add(new KeyValuePair<Guid, int>(id,0));
   
            using (Stream stream =request.GetBufferlessInputStream())
            {
                using (FileStream fs = new FileStream(fileFullPath, FileMode.OpenOrCreate))
                {
                   long size = long.Parse(request.Headers["Content-Length"]);
                   int maxIterations = (int)(size / (64 * 1024));
   
                   int chunkLength = 64 * 1024;
                   byte[] buffer = new byte[chunkLength];
                   int dataCaptured = 0;
                   for (int i = 0;i <= maxIterations; i++)
                   {
                       if (i <maxIterations)
                       {
                            stream.Read(buffer,0, chunkLength);
                            dataCaptured +=chunkLength;
                       }
                       else
                       {
                            buffer = new byte[(int)stream.Length- dataCaptured];
                            stream.Read(buffer,0, buffer.Length);
                       }
   
                       int positionToRemove = 0;
                       int bytesToGet = buffer.Length;
                       if (i == 0)
                       {
                            int numberOfFounds = 0;
                            bool canBe = false;
                            for (int j = 0; j < buffer.Length; j++)
                            {
                                if (buffer[j] == 13)
                                {
                                    canBe = true;
                                }
                                else
                                {
                                    if (canBe && buffer[j] == 10)
                                    {
                                       numberOfFounds++;
                                        if (numberOfFounds == 4)
                                        {
                                           positionToRemove = j + 1;
                                            byte[] headerBytes = new byte[positionToRemove];
                                            Array.Copy(buffer, headerBytes, positionToRemove);
                                           fileHeader = ASCIIEncoding.ASCII.GetString(headerBytes);
                                           bytesToGet = buffer.Length - positionToRemove;
                                           break;
                                        }
                                        canBe =false;
                                    }
                                    else
                                    {
                                        canBe =false;
                                    }
                                }
                            }
                       }
   
                       if ((int)stream.Length- buffer.Length - dataCaptured <= 49)
                       {
                            bytesToGet =bytesToGet - 48;
                       }
   
                       fs.Write(buffer, positionToRemove, bytesToGet);
                       requests[id] = (int)((float)((float)(i + 1) * ((float)size / maxIterations) / size) * 100);
                   }
   
                   int filenameStartIndex =fileHeader.IndexOf("filename=\"") + "filename=\"".Length;
                   int filenameEndIndex =fileHeader.Substring(filenameStartIndex).IndexOf("\"");
                   realFileName = Path.GetFileName(fileHeader.Substring(filenameStartIndex,filenameEndIndex));
                }
            }
   
            File.Move(fileFullPath, fileFullPath.Replace(filename,realFileName));
        }
   
        public static int CheckProgress(Guid id)
        {
            if (requests.ContainsKey(id))
                return requests[id];
   
            return -1;
        }
    }
}